package org.matrix.base
{
	import flashx.textLayout.formats.Direction;
	
	import mx.skins.spark.DefaultButtonSkin;
	

	public class Matrix2D extends Object implements IMatrix
	{
		internal var depth:uint;
		public function get dimensions():uint			{return 2}
		
		internal var numberOfItems:uint;
		
		public function Matrix2D(depth:uint)
		{
			super();
			this.depth = depth;
			numberOfItems = Math.pow(depth, dimensions);
			d2Lenght = depth * depth;
			init();
		}
		
		internal var d2Lenght:uint;
		protected var d2Index:uint;
		internal var d2Dirty:Boolean;
		internal var d2:Vector.<Vector.<Number>>;
			
		protected function init():void
		{
			d2 = new Vector.<Vector.<Number>>(depth, true);
			for (var i:uint = depth; i -- >= 1 ;)
				d2[i] = new Vector.<Number>(depth, true);
			d1 = d2[0];
		}
		
		public function setElement(value:Number, ... keys:Array):void	{d2[keys.unshift()][keys.unshift()] = value}
		public function getElement( ... keys:Array):Number				{return d2[keys.unshift()][keys.unshift()]}
		
//		protected var _index:uint;
//		public function get index():uint				{return _index}
		
		public function get index():uint				{return d2Index * depth + d1Index}
		public function set index(index:uint):void
		{
			var delta:int = index - this.index;
			if (delta == 0)
				return;
			if (delta < 0)
				delta += numberOfItems;
			while (delta --> 0)
				inc(false);
			validate();
		}
		
		public function get next():Number				{inc();return	_current}
		public function set next(value:Number):void		{inc(false);	_current = d1[d1Index] = value}
			
		public function moveAndSet(value:Number, chIndex:int):void
		{
			switch (chIndex)
			{
				case depth:
					d2Inc();
				case 0:
					break;
				default:
					index += chIndex
			}
			_current = d1[d1Index] = value;
		}
		public function moveAndGet(chIndex:int):Number
		{
			switch (chIndex)
			{
				case depth:
					d2Inc();
				case 0:
					break;
				default:
					index += chIndex
			}
			return _current;
		}
		
		protected function d3Inc(recursive:Boolean = false):void
		{
			if (recursive)
				d2Index = 0;
			else
				throw new Error('')
		}
		
				
		final protected function d2Inc(recursive:Boolean = false):void
		{
			if (++ d2Index == depth)
				d3Inc(d2Dirty = true);
			if (recursive)
				d1Index = 0;
		}		
		
		internal var d1Index:uint = uint.MAX_VALUE;
		protected var d1Dirty:Boolean;
		protected var d1:Vector.<Number>;
		final protected function inc(update:Boolean = true):void
		{
			if (++ d1Index == depth)
			{
				d2Inc(d1Dirty = true);
				if (update)
					validate();
			}
			else if (update)
				_current = d1[d1Index];
		}
		
		protected var _current:Number;
		protected function validate():void
		{
			if (d1Dirty)
			{
				d1 = d2[d2Index];
				d1Dirty = false;
			}
			_current = d1[index];
		}
	}
}